﻿namespace MsForgeReboot.Tests.Areas.ControlPanel.Controllers {
    #region Usings

    using System.Collections.Generic;
    using System.Web.Mvc;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Moq;

    using MsForgeReboot.Framework.Entities;
    using MsForgeReboot.Framework.Interfaces;
    using MsForgeReboot.Framework.ViewModels;
    using MsForgeReboot.Web.Areas.ControlPanel.Controllers;

    using PagedList;

    #endregion

    [TestClass]
    public class UserGroupControllerTests {
        private Mock<IUserGroupService> userGroupService;

        [TestInitialize]
        public void TestInitialize() {
            this.userGroupService = new Mock<IUserGroupService>();
        }

        [TestCleanup]
        public void TestCleanUp() {
            this.userGroupService = null;
        }

        [TestMethod]
        public void InstantiateUserGroupController() {
            var controller = new UserGroupController(this.userGroupService.Object);
            Assert.IsNotNull(controller);
        }

        [TestMethod]
        public void ListAllUserGroups() {
            this.userGroupService.Setup(service => service.GetList(1, 10))
                .Returns(new List<UserGroup>().ToPagedList(1, 10));

            var controller = new UserGroupController(this.userGroupService.Object);

            var result = controller.Index() as ViewResult;

            Assert.IsInstanceOfType(result.Model, typeof(IPagedList<UserGroup>));

            this.userGroupService.VerifyAll();
        }

        [TestMethod]
        public void CreateNewUserGroupsForm() {
            var controller = new UserGroupController(this.userGroupService.Object);

            var result = controller.Create() as ViewResult;

            Assert.AreEqual(result.ViewName, "Edit");
            Assert.IsInstanceOfType(result.Model, typeof(UserGroupEditModel));
        }

        [TestMethod]
        public void SaveNewUserGroup() {
            var controller = new UserGroupController(this.userGroupService.Object);

            var model = new UserGroupEditModel {
                                                   Id = 0,
                                                   Title = "Test User Grupa",
                                                   Body = "The quick brown fox jumps over the lazy dog",
                                                   Author = new UserViewModel { Id = 123 }
                                               };

            var result = (RedirectToRouteResult)controller.Edit(model);
            Assert.AreEqual("Index", result.RouteValues["action"]);
            this.userGroupService.Verify(service => service.Save(It.IsAny<UserGroup>()), Times.Exactly(1));
        }

        [TestMethod]
        public void SaveNewUserGroupWhenUrlPointerAndPublisDateAreOmmitedInModel() {
            var controller = new UserGroupController(this.userGroupService.Object);

            var model = new UserGroupEditModel {
                                                   Id = 0,
                                                   Title = "Test User Grupa",
                                                   Body = "The quick brown fox jumps over the lazy dog",
                                                   Author = new UserViewModel { Id = 123 }
                                               };

            this.userGroupService.Setup(service => service.Save(It.IsAny<UserGroup>()));

            var result = controller.Edit(model) as RedirectToRouteResult;
            Assert.AreEqual("Index", result.RouteValues["action"]);

            this.userGroupService.VerifyAll();
        }

        [TestMethod]
        public void SaveNewUserGroupRedirectToEditIfModelStateIsInvalid() {
            var controller = new UserGroupController(this.userGroupService.Object);
            controller.ModelState.AddModelError("", "fake error message, simulation of defaultModelBinder behaviour");

            var expected = new UserGroupEditModel();

            var result = controller.Edit(expected) as ViewResult;

            Assert.AreSame(expected, result.Model);
            Assert.AreEqual("Edit", result.ViewName);

            this.userGroupService.Verify(service => service.Save(It.IsAny<UserGroup>()), Times.Never);
        }

        [TestMethod]
        public void SaveNewUserGroupRedirectToEditIfAuthorIsNull() {
            var controller = new UserGroupController(this.userGroupService.Object);
            var expected = new UserGroupEditModel { Title = "test", Body = "test", Author = null };

            var result = controller.Edit(expected) as ViewResult;

            Assert.AreSame(expected, result.Model);
            Assert.AreEqual("Edit", result.ViewName);

            this.userGroupService.Verify(service => service.Save(It.IsAny<UserGroup>()), Times.Never);
        }

        [TestMethod]
        public void SaveNewUserGroupRedirectToEditIfAuthorIdIsNotSpecified() {
            var controller = new UserGroupController(this.userGroupService.Object);

            var expected = new UserGroupEditModel { Title = "test", Body = "test", Author = { Id = 0 } };

            var result = controller.Edit(expected) as ViewResult;

            Assert.AreSame(expected, result.Model);
            Assert.AreEqual("Edit", result.ViewName);

            this.userGroupService.Verify(service => service.Save(It.IsAny<UserGroup>()), Times.Never);
        }

        [TestMethod]
        public void DeleteUserGroupByUrlPointer() {
            this.userGroupService.Setup(service => service.Delete("Title-1"));

            var controller = new UserGroupController(this.userGroupService.Object);

            var result = controller.Delete("Title-1") as JsonResult;

            Assert.AreEqual(result.Data, "success");
            Assert.AreEqual(result.JsonRequestBehavior, JsonRequestBehavior.DenyGet);

            this.userGroupService.VerifyAll();
        }

        [TestMethod]
        public void EditUserGroupByUrlPointer() {
            this.userGroupService.Setup(service => service.GetByUrlPointer("Title-1"))
                .Returns(
                    new UserGroup {
                                      Id = 20,
                                      Title = "Title 20",
                                      Body = "Body 20",
                                      Author = new User() { Id = 5, PublicName = "test public name 5" }
                                  });

            var controller = new UserGroupController(this.userGroupService.Object);

            var result = controller.Edit("Title-1") as ViewResult;
            var model = result.Model as UserGroupEditModel;

            Assert.AreEqual(model.Id, 20);
            Assert.AreEqual(model.Title, "Title 20");
            Assert.AreEqual(model.Body, "Body 20");
            Assert.AreEqual(model.Author.Id, 5);
            Assert.AreEqual(model.Author.PublicName, "test public name 5");

            this.userGroupService.VerifyAll();
        }
    }
}